/*
 *    Copyright (c) 2018-2025, boss All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the boss developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: boss
 */
package com.hopes.bizz.basic.safe.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hopes.bizz.basic.common.constant.FlowConstant;
import com.hopes.bizz.basic.common.constant.FlowDicConstant;
import com.hopes.bizz.basic.common.constant.enums.ParkBasicSysDictEnum;
import com.hopes.bizz.basic.drive.bo.BaseTaskBo;
import com.hopes.bizz.basic.drive.dto.BaseAuditDTO;
import com.hopes.bizz.basic.safe.dto.BaseThreeMeantimeExcelDTO;
import com.hopes.bizz.basic.safe.entity.BaseThreeMeantimeEntity;
import com.hopes.bizz.basic.safe.entity.BaseThreeMeantimeHandleRecordEntity;
import com.hopes.bizz.basic.safe.mapper.BaseThreeMeantimeMapper;
import com.hopes.bizz.basic.safe.service.BaseThreeMeantimeHandleRecordService;
import com.hopes.bizz.basic.safe.service.BaseThreeMeantimeService;
import com.hopes.bizz.basic.safe.vo.BaseThreeMeantimeExcelVO;
import com.hopes.bizz.basic.safe.vo.BaseThreeMeantimeGisVo;
import com.hopes.bizz.common.core.validate.ValidatorUtils;
import com.hopes.boss.act.base.FlowServiceImpl;
import com.hopes.boss.act.base.TaskExecute;
import com.hopes.boss.act.enums.FlowTaskHandlerType;
import com.hopes.boss.act.vo.FlowTaskInfo;
import com.hopes.boss.admin.api.resolver.DictResolver;
import com.hopes.boss.admin.api.resolver.enums.AdminDictEnum;
import com.hopes.boss.common.entity.ValidateImportBO;
import com.hopes.boss.common.excel.vo.ErrorMessage;
import com.hopes.boss.common.security.util.SecurityUtils;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 项目三同时管理
 *
 * @author pig
 * @date 2023-10-30 09:59:17
 */
@Service
public class BaseThreeMeantimeServiceImpl extends FlowServiceImpl<BaseThreeMeantimeMapper, BaseThreeMeantimeEntity> implements BaseThreeMeantimeService {

    @Autowired
    private BaseThreeMeantimeHandleRecordService baseThreeMeantimeHandleRecordService;

    @Override
    public ValidateImportBO<BaseThreeMeantimeExcelDTO> validateImport(List<BaseThreeMeantimeExcelDTO> excelDTOList) {
        ValidateImportBO<BaseThreeMeantimeExcelDTO> bo = new ValidateImportBO<>();
        List<ErrorMessage> errorMessageList = new ArrayList<>();
        List<BaseThreeMeantimeExcelDTO> saveList = new ArrayList<>();
        int successNum = 0;
        int failedNum = 0;
        for (BaseThreeMeantimeExcelDTO baseThreeMeantimeExcelDTO : excelDTOList) {
            String validateRes = ValidatorUtils.validateEntity(baseThreeMeantimeExcelDTO);
            if (StrUtil.isEmpty(validateRes)) {
                successNum++;
                saveList.add(baseThreeMeantimeExcelDTO);
            } else {
                failedNum++;
                errorMessageList.add(new ErrorMessage(baseThreeMeantimeExcelDTO.getLineNum(), new HashSet<String>() {{
                    add(validateRes);
                }}));
            }
        }
        bo.setErrorMessages(errorMessageList);
        bo.setSaveList(saveList);
        bo.setSuccessNum(successNum);
        bo.setFailedNum(failedNum);
        return bo;
    }

    @Override
    public BaseThreeMeantimeEntity importDtoToEntity(BaseThreeMeantimeExcelDTO excelDto) {
        BaseThreeMeantimeEntity entity = new BaseThreeMeantimeEntity();
        BeanUtils.copyProperties(excelDto, entity);
        entity.setOrgId(Long.valueOf(DictResolver.getItemValueByLabel(AdminDictEnum.sys_company, excelDto.getOrgId())));
        entity.setProjectType(DictResolver.getItemValueByLabel(ParkBasicSysDictEnum.project_type, excelDto.getProjectType()));
        entity.setProjectStatus(DictResolver.getItemValueByLabel(ParkBasicSysDictEnum.audit_status, excelDto.getProjectStatus()));
        return entity;
    }

    @Override
    public BaseThreeMeantimeExcelVO exportEntityToVo(BaseThreeMeantimeEntity entity) {
        BaseThreeMeantimeExcelVO excelVO = new BaseThreeMeantimeExcelVO();
        BeanUtils.copyProperties(entity, excelVO);
        return excelVO;
    }

    @Override
    public BaseThreeMeantimeGisVo getThreeMeantime() {
        BaseThreeMeantimeGisVo baseThreeMeantimeGisVo = new BaseThreeMeantimeGisVo();
        JSONObject barData = new JSONObject();
        JSONArray pieData = new JSONArray();
        baseThreeMeantimeGisVo.setBarData(barData);
        baseThreeMeantimeGisVo.setPieData(pieData);
        List<BaseThreeMeantimeEntity> threeMeantimeEntities = baseMapper.selectList(null);
        // 项目类别统计
        Map<String, Long> projectTypeMap = threeMeantimeEntities.stream().collect(Collectors.groupingBy(BaseThreeMeantimeEntity::getProjectType, Collectors.counting()));
        projectTypeMap.forEach((k, v) -> {
            JSONObject data = new JSONObject();
            data.put("name", DictResolver.getItemLabelByValue(ParkBasicSysDictEnum.project_type, k));
            data.put("value", v);
            pieData.add(data);
        });
        // 项目阶段分类统计
        Map<String, Long> projectStatusMap = threeMeantimeEntities.stream().collect(Collectors.groupingBy(BaseThreeMeantimeEntity::getProjectStatus, Collectors.counting()));
        ArrayList<String> name = new ArrayList<>(projectStatusMap.size());
        ArrayList<Long> count = new ArrayList<>(projectStatusMap.size());
        barData.put("name",name);
        barData.put("count",count);
        projectStatusMap.forEach((k, v) -> {
            name.add(DictResolver.getItemLabelByValue(ParkBasicSysDictEnum.audit_status, k));
            count.add(v);
        });
        return baseThreeMeantimeGisVo;
    }

    @Override
    @GlobalTransactional // 分布式事务注解
    public void handlerAudit(BaseAuditDTO baseAuditDTO) {
        Long id = baseAuditDTO.getId();
        FlowTaskHandlerType flowTaskHandlerType = FlowTaskHandlerType.getFlowTaskHandlerTypeByCode(baseAuditDTO.getHandleResult());
        // 提交工作流
        BaseTaskBo baseTaskBo = new BaseTaskBo()
                .setHandleResultDesc(baseAuditDTO.getHandleResultDesc())
                .setAttachment(baseAuditDTO.getAttachment())
                .setHandleTime(baseAuditDTO.getHandleTime())
                .setSignature(baseAuditDTO.getSignature());
        TaskExecute taskExecute = new TaskExecute.Build()
                .setBusinessKey(id)
                .setFlowTaskHandlerType(flowTaskHandlerType)
                .setBusinessData(baseTaskBo)
                .build();
        executeTask(taskExecute);
    }

    @Override
    @GlobalTransactional // 分布式事务注解
    public void handleThreeMeantimeSubmit(Long id) {
        TaskExecute taskExecute = new TaskExecute.Build()
                .setBusinessKey(id)
                .setFlowTaskHandlerType(FlowTaskHandlerType.TASK_HANDLE_TYPE_SUBMIT)
                .build();
        executeTask(taskExecute);
    }

    @Override
    public void doCompletedTask(FlowTaskInfo flowTaskInfo, Long id, FlowTaskHandlerType handlerType, Object data) {
        // 提交操作创建当前节点和下一节点
        if (FlowTaskHandlerType.TASK_HANDLE_TYPE_SUBMIT.equals(handlerType)) {
            BaseThreeMeantimeHandleRecordEntity startNode = new BaseThreeMeantimeHandleRecordEntity();
            startNode.setNodeCode(FlowDicConstant.START);
            startNode.setBusinessId(id);
            startNode.setHandleUserId(SecurityUtils.getUserId());
            startNode.setHandleTime(new Date());
            baseThreeMeantimeHandleRecordService.save(startNode);
            // 下一节点
            BaseThreeMeantimeHandleRecordEntity nextNode = new BaseThreeMeantimeHandleRecordEntity();
            nextNode.setNodeCode(flowTaskInfo.getStatus());
            nextNode.setBusinessId(id);
            nextNode.setExecutor(flowTaskInfo.getCandidateStr());
            baseThreeMeantimeHandleRecordService.save(nextNode);
            // 更新当前纪录为填报中
            lambdaUpdate().set(BaseThreeMeantimeEntity::getProjectStatus, FlowDicConstant.IN_REVIEW)
                    .eq(BaseThreeMeantimeEntity::getId, id).update();
        } else {
            BaseTaskBo baseTaskBo = (BaseTaskBo) data;
            // 通过 更新上一节点
            BaseThreeMeantimeEntity overhaulRecord = getById(id);
            BaseThreeMeantimeHandleRecordEntity preRecord = baseThreeMeantimeHandleRecordService.lambdaQuery()
                    .eq(BaseThreeMeantimeHandleRecordEntity::getBusinessId, id)
                    .eq(BaseThreeMeantimeHandleRecordEntity::getNodeCode, overhaulRecord.getProjectStatus())
                    .orderByDesc(BaseThreeMeantimeHandleRecordEntity::getCreateTime)
                    .select(BaseThreeMeantimeHandleRecordEntity::getId)
                    .last("limit 1")
                    .one();
            baseThreeMeantimeHandleRecordService.lambdaUpdate()
                    .eq(BaseThreeMeantimeHandleRecordEntity::getId, preRecord.getId())
                    .set(BaseThreeMeantimeHandleRecordEntity::getHandleUserId, SecurityUtils.getUserId())
                    .set(BaseThreeMeantimeHandleRecordEntity::getHandleResultDesc, baseTaskBo.getHandleResultDesc())
                    .set(BaseThreeMeantimeHandleRecordEntity::getHandleTime, baseTaskBo.getHandleTime())
                    .set(BaseThreeMeantimeHandleRecordEntity::getAttachment, baseTaskBo.getAttachment())
                    .set(BaseThreeMeantimeHandleRecordEntity::getSignature, baseTaskBo.getSignature())
                    .set(BaseThreeMeantimeHandleRecordEntity::getHandleResult, handlerType.getName())
                    .update();
        }
        if (FlowTaskHandlerType.TASK_HANDLE_TYPE_PASS.equals(handlerType)) {
            // 更新当前纪录为审核通过
            lambdaUpdate().set(BaseThreeMeantimeEntity::getProjectStatus, FlowDicConstant.PASS)
                    .eq(BaseThreeMeantimeEntity::getId, id).update();
        } else if (FlowTaskHandlerType.TASK_HANDLE_TYPE_BACK.equals(handlerType)) {
            // 更新当前纪录为审核通过
            lambdaUpdate().set(BaseThreeMeantimeEntity::getProjectStatus, FlowDicConstant.NOT_PASS)
                    .eq(BaseThreeMeantimeEntity::getId, id).update();
        }
    }


    @Override
    public void savePlan(BaseThreeMeantimeHandleRecordEntity baseThreeMeantimeHandleRecord) {
        // 处理进度
        String planStatus = baseThreeMeantimeHandleRecord.getHandleResult();
        // 业务id
        Long businessId = baseThreeMeantimeHandleRecord.getBusinessId();
        // 更新项目进度
        lambdaUpdate().set(BaseThreeMeantimeEntity::getPlanStatus,planStatus).eq(BaseThreeMeantimeEntity::getId,businessId).update();
        // 纪录处理进度
        baseThreeMeantimeHandleRecord.setHandleUserId(SecurityUtils.getUserId());
        baseThreeMeantimeHandleRecord.setHandleResult(DictResolver.getItemLabelByValue(ParkBasicSysDictEnum.project_plan,planStatus));
        baseThreeMeantimeHandleRecordService.save(baseThreeMeantimeHandleRecord);

    }

    @Override
    public void deleteBusiness(Collection<Long> meantimeList) {
        // 删除相关处理纪录
        baseThreeMeantimeHandleRecordService.remove(Wrappers.lambdaQuery(BaseThreeMeantimeHandleRecordEntity.class).in(BaseThreeMeantimeHandleRecordEntity::getBusinessId, meantimeList));
    }

    @Override
    public String getFlowDefinitionKey(Long id) {

        return FlowConstant.BASE_THREE_MEANTIME;
    }
}
